/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
var mxMarker =
{
  /**
	 * Class: mxMarker
	 *
	 * A static class that implements all markers for VML and SVG using a
	 * registry. NOTE: The signatures in this class will change.
	 *
	 * Variable: markers
	 *
	 * Maps from markers names to functions to paint the markers.
	 */
  markers: [],

  /**
	 * Function: addMarker
	 *
	 * Adds a factory method that updates a given endpoint and returns a
	 * function to paint the marker onto the given canvas.
	 */
  addMarker: function (type, funct) {
    mxMarker.markers[type] = funct
  },

  /**
	 * Function: createMarker
	 *
	 * Returns a function to paint the given marker.
	 */
  createMarker: function (canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
    var funct = mxMarker.markers[type]

    return (funct != null) ? funct(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) : null
  }

};

/**
 * Adds the classic and block marker factory method.
 */
(function () {
  function createArrow (widthFactor) {
    widthFactor = (widthFactor != null) ? widthFactor : 2

    return function (canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
      // The angle of the forward facing arrow sides against the x axis is
      // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
      // only half the strokewidth is processed ).
      var endOffsetX = unitX * sw * 1.118
      var endOffsetY = unitY * sw * 1.118

      unitX = unitX * (size + sw)
      unitY = unitY * (size + sw)

      var pt = pe.clone()
      pt.x -= endOffsetX
      pt.y -= endOffsetY

      var f = (type != mxConstants.ARROW_CLASSIC && type != mxConstants.ARROW_CLASSIC_THIN) ? 1 : 3 / 4
      pe.x += -unitX * f - endOffsetX
      pe.y += -unitY * f - endOffsetY

      return function () {
        canvas.begin()
        canvas.moveTo(pt.x, pt.y)
        canvas.lineTo(pt.x - unitX - unitY / widthFactor, pt.y - unitY + unitX / widthFactor)

        if (type == mxConstants.ARROW_CLASSIC || type == mxConstants.ARROW_CLASSIC_THIN) {
          canvas.lineTo(pt.x - unitX * 3 / 4, pt.y - unitY * 3 / 4)
        }

        canvas.lineTo(pt.x + unitY / widthFactor - unitX, pt.y - unitY - unitX / widthFactor)
        canvas.close()

        if (filled) {
          canvas.fillAndStroke()
        } else {
          canvas.stroke()
        }
      }
    }
  };

  mxMarker.addMarker('classic', createArrow(2))
  mxMarker.addMarker('classicThin', createArrow(3))
  mxMarker.addMarker('block', createArrow(2))
  mxMarker.addMarker('blockThin', createArrow(3))

  function createOpenArrow (widthFactor) {
    widthFactor = (widthFactor != null) ? widthFactor : 2

    return function (canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
      // The angle of the forward facing arrow sides against the x axis is
      // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
      // only half the strokewidth is processed ).
      var endOffsetX = unitX * sw * 1.118
      var endOffsetY = unitY * sw * 1.118

      unitX = unitX * (size + sw)
      unitY = unitY * (size + sw)

      var pt = pe.clone()
      pt.x -= endOffsetX
      pt.y -= endOffsetY

      pe.x += -endOffsetX * 2
      pe.y += -endOffsetY * 2

      return function () {
        canvas.begin()
        canvas.moveTo(pt.x - unitX - unitY / widthFactor, pt.y - unitY + unitX / widthFactor)
        canvas.lineTo(pt.x, pt.y)
        canvas.lineTo(pt.x + unitY / widthFactor - unitX, pt.y - unitY - unitX / widthFactor)
        canvas.stroke()
      }
    }
  };

  mxMarker.addMarker('open', createOpenArrow(2))
  mxMarker.addMarker('openThin', createOpenArrow(3))

  mxMarker.addMarker('oval', function (canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
    var a = size / 2

    var pt = pe.clone()
    pe.x -= unitX * a
    pe.y -= unitY * a

    return function () {
      canvas.ellipse(pt.x - a, pt.y - a, size, size)

      if (filled) {
        canvas.fillAndStroke()
      } else {
        canvas.stroke()
      }
    }
  })

  function diamond (canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
    // The angle of the forward facing arrow sides against the x axis is
    // 45 degrees, 1/sin(45) = 1.4142 / 2 = 0.7071 ( / 2 allows for
    // only half the strokewidth is processed ). Or 0.9862 for thin diamond.
    // Note these values and the tk variable below are dependent, update
    // both together (saves trig hard coding it).
    var swFactor = (type == mxConstants.ARROW_DIAMOND) ? 0.7071 : 0.9862
    var endOffsetX = unitX * sw * swFactor
    var endOffsetY = unitY * sw * swFactor

    unitX = unitX * (size + sw)
    unitY = unitY * (size + sw)

    var pt = pe.clone()
    pt.x -= endOffsetX
    pt.y -= endOffsetY

    pe.x += -unitX - endOffsetX
    pe.y += -unitY - endOffsetY

    // thickness factor for diamond
    var tk = ((type == mxConstants.ARROW_DIAMOND) ? 2 : 3.4)

    return function () {
      canvas.begin()
      canvas.moveTo(pt.x, pt.y)
      canvas.lineTo(pt.x - unitX / 2 - unitY / tk, pt.y + unitX / tk - unitY / 2)
      canvas.lineTo(pt.x - unitX, pt.y - unitY)
      canvas.lineTo(pt.x - unitX / 2 + unitY / tk, pt.y - unitY / 2 - unitX / tk)
      canvas.close()

      if (filled) {
        canvas.fillAndStroke()
      } else {
        canvas.stroke()
      }
    }
  };

  mxMarker.addMarker('diamond', diamond)
  mxMarker.addMarker('diamondThin', diamond)
})()
